This document aims at exploring the dataset of 9 southern-individuals in 2014. For that purpose, we need first to load the weanlingNES package to load data.
# load library
library(weanlingNES)
# load data
data("data_ses", package = "weanlingNES")
# load("../data/data_ses.rda")
Let’s have a look at what’s inside data_ses$data_2014:
# list structure
str(data_ses$year_2014, max.level = 1, give.attr = F, no.list = T)
## $ ind_140059:Classes 'data.table' and 'data.frame': 2305 obs. of 45 variables:
## $ ind_140060:Classes 'data.table' and 'data.frame': 1866 obs. of 45 variables:
## $ ind_140062:Classes 'data.table' and 'data.frame': 2619 obs. of 45 variables:
## $ ind_140063:Classes 'data.table' and 'data.frame': 1570 obs. of 45 variables:
## $ ind_140068:Classes 'data.table' and 'data.frame': 1904 obs. of 45 variables:
## $ ind_140069:Classes 'data.table' and 'data.frame': 2123 obs. of 45 variables:
## $ ind_140072:Classes 'data.table' and 'data.frame': 2625 obs. of 45 variables:
## $ ind_140073:Classes 'data.table' and 'data.frame': 1692 obs. of 45 variables:
## $ ind_140075:Classes 'data.table' and 'data.frame': 1451 obs. of 45 variables:
A list of 9 data.frames, one for each seal
For convenience, we aggregate all 9 individuals into one dataset.
# combine all individuals
data_2014 <- rbindlist(data_ses$year_2014)
# display
DT::datatable(data_2014[sample.int(.N, 10), ], options = list(scrollX = T))
Table 1: Sample of 10 random rows from data_2014
Summary
# raw_data
data_2014[, .(
nb_days_recorded = uniqueN(as.Date(date)),
nb_dives = .N,
maxdepth_mean = mean(maxdepth),
dduration_mean = mean(dduration),
botttime_mean = mean(botttime),
pdi_mean = mean(pdi, na.rm = T)
), by = .id] %>%
sable(
caption = "Summary diving information relative to each 2018 individual",
digits = 2
)
Table 2: Summary diving information relative to each 2018 individual
|
.id
|
nb_days_recorded
|
nb_dives
|
maxdepth_mean
|
dduration_mean
|
botttime_mean
|
pdi_mean
|
|
ind_140059
|
238
|
2305
|
216.36
|
750.18
|
394.32
|
8218.73
|
|
ind_140060
|
189
|
1866
|
188.91
|
580.63
|
269.35
|
7903.56
|
|
ind_140062
|
264
|
2619
|
148.45
|
561.22
|
296.67
|
8643.92
|
|
ind_140063
|
159
|
1570
|
175.05
|
614.46
|
307.30
|
7779.18
|
|
ind_140068
|
192
|
1904
|
165.77
|
663.89
|
336.68
|
7950.71
|
|
ind_140069
|
212
|
2123
|
174.01
|
549.01
|
259.39
|
8052.52
|
|
ind_140072
|
264
|
2625
|
173.33
|
571.55
|
244.76
|
7928.25
|
|
ind_140073
|
176
|
1692
|
190.48
|
617.03
|
276.21
|
7850.67
|
|
ind_140075
|
141
|
1451
|
132.48
|
465.18
|
194.11
|
7837.99
|
Some explanatory plots
Missing values
# build dataset to check for missing values
dataPlot <- melt(data_2014[, .(.id, is.na(.SD)), .SDcol = -c(
".id",
"divenumber",
"year",
"month",
"day",
"hour",
"min",
"sec",
"juldate",
"divetype",
"date"
# "phase",
# "lat",
# "lon"
)])
# add the id of rows
dataPlot[, id_row := c(1:.N), by = c("variable", ".id")]
# plot
ggplot(dataPlot, aes(x = variable, y = id_row, fill = value)) +
geom_tile() +
labs(x = "Attributes", y = "Rows") +
scale_fill_manual(
values = c("white", "black"),
labels = c("Real", "Missing")
) +
facet_wrap(.id ~ ., scales = "free_y") +
theme_jjo() +
theme(
legend.position = "top",
axis.text.x = element_text(angle = 45, hjust = 1),
legend.key = element_rect(colour = "black")
)
Let’s look closer to the variables with missing values:
# table with percent
table_inter <- data_2014[, lapply(.SD, function(x) {
round(length(x[is.na(x)]) * 100 / length(x), 1)
}), .SDcol = -c(
".id",
"divenumber",
"year",
"month",
"day",
"hour",
"min",
"sec",
"juldate",
"divetype",
"date"
# "phase",
# "lat",
# "lon"
)]
# find which are different from 0
cond_inter <- sapply(table_inter, function(x) {
x == 0
})
# display the percentages that are over 0
table_inter[, which(cond_inter) := NULL] %>%
sable(caption = "Percentage of missing values per columns having missing values!") %>%
scroll_box(width = "100%")
Table 3: Percentage of missing values per columns having missing values!
|
driftrate
|
benthicdivevertrate
|
cornerindex
|
foragingindex
|
verticalspeed90perc
|
verticalspeed95perc
|
|
4.7
|
27
|
68.6
|
0.5
|
4.5
|
4.5
|
Nothing bad, missing values seem to occur only in column we are not interested in.
Outliers
Let’s see if we have some outliers. Some of them are quiet easy to spot looking at the distribution of dive duration:
# plot that, weirdly, doesn't free x axis...
# ggplot(
# melt(data_2014,
# id.vars = c(".id"),
# measure.vars = c("dduration","maxdepth","driftrate")),
# aes(x = value, fill = .id)
# ) +
# geom_histogram(show.legend = FALSE) +
# facet_grid(variable ~ .id,
# scales = "free"
# ) +
# labs(y = "# of dives") +
# theme_jjo()
ggplot(
melt(data_2014,
id.vars = c(".id"),
measure.vars = c("dduration")
),
aes(x = value, fill = .id)
) +
geom_histogram(show.legend = FALSE) +
facet_grid(variable ~ .id,
scales = "free"
) +
labs(y = "# of dives") +
theme_jjo() +
theme(
axis.title.x = element_blank(),
text = element_text(size = 8)
)
ggplot(
melt(data_2014,
id.vars = c(".id"),
measure.vars = c("maxdepth")
),
aes(x = value, fill = .id)
) +
geom_histogram(show.legend = FALSE) +
facet_grid(variable ~ .id,
scales = "free"
) +
scale_y_reverse() +
labs(y = "# of dives") +
theme_jjo() +
theme(
strip.text.x = element_blank(),
axis.title.x = element_blank(),
text = element_text(size = 8)
)
ggplot(
melt(data_2014,
id.vars = c(".id"),
measure.vars = c("driftrate")
),
aes(x = value, fill = .id)
) +
geom_histogram(show.legend = FALSE) +
facet_grid(variable ~ .id,
scales = "free"
) +
labs(y = "# of dives") +
theme_jjo() +
theme(
strip.text.x = element_blank(),
text = element_text(size = 8)
)
Nothing that obvious, which is great :)
All Variables
names_display <- names(data_2014[, -c(
".id",
"date",
"divenumber",
"year",
"month",
"day",
"hour",
"min",
"sec",
"juldate",
"divetype",
"day_departure",
"phase",
"lat",
"lon",
"sp"
)])
# calulate the median of driftrate for each day
median_driftrate <- data_2014[divetype == "2: drift",
.(driftrate = quantile(driftrate, 0.5)),
by = .(date = as.Date(date), .id)
]
# let's identity when the smooth changes sign
changes_driftrate <- median_driftrate %>%
.[, .(
y_smooth = predict(loess(driftrate ~ as.numeric(date), span = 0.25)),
date
), by = .id] %>%
.[c(FALSE, diff(sign(y_smooth)) != 0), ]
Full trip duration
for (i in names_display) {
cat("#####", i, "{.unlisted .unnumbered} \n")
if (i == "driftrate") {
print(
ggplot(
data = melt(data_2014[, .(.id, date, get(i), divetype)],
id.vars = c(".id", "date", "divetype")
),
aes(
x = as.Date(date),
y = value,
col = divetype
)
) +
geom_point(
alpha = 1 / 10,
size = .5
) +
geom_vline(
data = changes_driftrate,
aes(xintercept = date),
linetype = 2
) +
facet_wrap(. ~ .id, scales = "free") +
scale_x_date(date_labels = "%m/%Y") +
labs(x = "Date", y = "Drift Rate m/s", col = "Dive Type") +
theme_jjo() +
theme(
axis.text.x = element_text(angle = 45, hjust = 1),
legend.position = "bottom"
) +
guides(colour = guide_legend(override.aes = list(
size = 7,
alpha = 1
)))
)
} else {
print(
ggplot(
data = melt(data_2014[, .(.id, date, get(i))],
id.vars = c(".id", "date")
),
aes(
x = as.Date(date),
y = value,
col = .id
)
) +
geom_point(
show.legend = FALSE,
alpha = 1 / 10,
size = .5
) +
geom_vline(
data = changes_driftrate,
aes(xintercept = date),
linetype = 2
) +
facet_wrap(. ~ .id, scales = "free") +
scale_x_date(date_labels = "%m/%Y") +
labs(x = "Date", y = i) +
theme_jjo() +
theme(axis.text.x = element_text(angle = 45, hjust = 1))
)
}
cat("\n \n")
}
The vertical dashed lines represent changes in buoyancy (see vignette("buoyancy_detect") for more information)
maxdepth

dduration

botttime

desctime

descrate

asctime

ascrate

pdi

dwigglesdesc

dwigglesbott

dwigglesasc

totvertdistbot

bottrange

efficiency

idz

driftdiveindex

driftrate

benthicdiveindex

benthicdivevertrate

cornerindex

foragingindex

verticalspeed90perc

verticalspeed95perc

dist_dep

temp

ssh

psu

vel

bathy

First month at sea
for (i in names_display) {
# subtitle
cat("#####", i, "{.unlisted .unnumbered} \n")
# print plot
print(
ggplot(
data = melt(data_2014[day_departure < 32,
.(.id, day_departure, get(i))],
id.vars = c(".id", "day_departure")),
aes(
x = day_departure,
y = value,
color = .id,
group = day_departure
)
) +
geom_boxplot(
show.legend = FALSE,
alpha = 1 / 10,
size = .5
) +
facet_wrap(. ~ .id, scales = "free") +
labs(x = "# days since departure", y = i) +
theme_jjo()
)
cat("\n \n")
}
maxdepth

dduration

botttime

desctime

descrate

asctime

ascrate

pdi

dwigglesdesc

dwigglesbott

dwigglesasc

totvertdistbot

bottrange

efficiency

idz

driftdiveindex

driftrate

benthicdiveindex

benthicdivevertrate

cornerindex

foragingindex

verticalspeed90perc

verticalspeed95perc

dist_dep

temp

ssh

psu

vel

bathy

Dive Type
# dataset to plot proportional area plot
data_2014[, sum_id := .N, by = .(.id, day_departure)] %>%
.[, sum_id_days := .N, by = .(.id, day_departure, divetype)] %>%
.[, prop := sum_id_days / sum_id]
dataPlot <- unique(data_2014[, .(prop, .id, divetype, day_departure)])
# area plot
ggplot(dataPlot, aes(
x = as.numeric(day_departure),
y = prop,
fill = as.character(divetype)
)) +
geom_area(alpha = 0.6, size = 1) +
facet_wrap(.id ~ ., scales = "free") +
theme_jjo() +
theme(legend.position = "bottom") +
labs(x = "# of days since departure",
y = "Proportion of dives",
fill = "Dive types")
Drift Rate
In the following graphs:
driftrate is calculated using only divetype == "2: drift"
- whereas all the others variables are calculated all dives considered
- Dives were
driftrate > 0 were excluded
# build dataset
dataPlot <- data_2014[divetype == "2: drift" &
driftrate < 0,
# median drift rate for drift dive
.(driftrate = median(driftrate, na.rm = T)),
by = .(.id, day_departure)] %>%
# merge to get other parameters including all dives
.[data_2014[driftrate < 0,
.(
# median dive duration all dives considered
dduration = median(dduration, na.rm = T),
# median max depth all dives considered
maxdepth = median(maxdepth, na.rm = T),
# median bottom dives all dives considered
botttime = median(botttime, na.rm = T)
),
by = .(.id, day_departure)],
on = c(".id", "day_departure")]
# plot
ggplot(dataPlot, aes(x = botttime, y = driftrate, col = .id)) +
geom_point(size = .5, alpha = .5) +
geom_smooth(method = "lm") +
guides(color = "none") +
facet_wrap(.id ~ .) +
scale_x_continuous(limits = c(0, 700)) +
labs(x = "Daily median Bottom time (s)",
y = "Daily median drift rate (m.s-1)") +
theme_jjo()
# plot
ggplot(dataPlot, aes(x = maxdepth, y = driftrate, col = .id)) +
geom_point(size = .5, alpha = .5) +
geom_smooth(method = "lm") +
guides(color = "none") +
scale_y_reverse() +
facet_wrap(.id ~ .) +
labs(x = "Daily median Maximum depth (m)",
y = "Daily median drift rate (m.s-1)") +
theme_jjo()
# plot
ggplot(dataPlot, aes(x = dduration, y = driftrate, col = .id)) +
geom_point(size = .5, alpha = .5) +
geom_smooth(method = "lm") +
guides(color = "none") +
facet_wrap(.id ~ .) +
labs(x = "Daily median Dive duration (s)",
y = "Daily median drift rate (m.s-1)") +
theme_jjo()
Behavioral Aerobic Dive Limit (bADL)
Based on Shero et al. (2018), we decided to look at the bADL as the 95th percentile of dive duration each day, for those with \(n \geq 8\). This threshold was chosen following this figure, please note that this number is particularly low cause only one dive every 2.2 hours was sampled:
ggplot(data_2014[,.(nb_dives = .N),
by = .(.id, day_departure)],
aes(x=nb_dives, fill=.id)) +
geom_histogram(show.legend = FALSE) +
facet_wrap(.~.id) +
labs(y="# of days", x = "# of dives per day") +
theme_jjo() +
theme(text = element_text(size = 8))
# select day that have at least 50 dives
days_to_keep = data_2014[,
.(nb_dives = .N),
by = .(.id, day_departure)] %>%
.[nb_dives >= 8,]
# keep only those days
data_2014_complete_day = merge(data_2014,
days_to_keep,
by = c(".id", "day_departure"))
# data plot
dataPlot = data_2014_complete_day[divetype=="1: foraging",
.(badl = quantile(dduration, 0.95)),
by = .(.id, day_departure)]
# combine two datasets to be able to use a second axis
# https://stackoverflow.com/questions/49185583/two-y-axes-with-different-scales-for-two-datasets-in-ggplot2
dataMegaPlot = rbind(data_2014_complete_day[divetype == "2: drift"] %>%
.[, .(w = .id,
y = driftrate,
x = day_departure,
z = "second_plot")],
dataPlot[, .(
w = .id,
# tricky one
y = (badl / 1000) - 1,
x = day_departure,
z = "first_plot"
)])
# plot
ggplot() +
geom_point(
data = dataMegaPlot[z == "second_plot", ],
aes(x = x, y = y),
alpha = 1 / 10,
size = 0.5,
color = "grey40",
show.legend = FALSE
) +
geom_path(data = dataMegaPlot[z == "first_plot", ],
aes(x = x, y = y, color = w),
show.legend = FALSE) +
scale_y_continuous(
# Features of the first axis
name = "Drift rate (m/s)",
# Add a second axis and specify its features
sec.axis = sec_axis( ~ (. * 1000) + 1000,
name = "Behavioral Aerobic Dive Limit (s)")
) +
labs(x = "# days since departure") +
facet_wrap(w ~ .) +
theme_jjo()
Looking at this graph, I want to believe that there is some kind of relationship between the bADL as defined by Shero et al. (2018) and the drift rate (and so buyoancy).
# get badl
dataplot_1 = data_2014_complete_day[,
.(badl = quantile(dduration, 0.95)),
by = .(.id, day_departure)]
# get driftrate
dataplot_2 = data_2014_complete_day[divetype == "2: drift",
.(driftrate = median(driftrate)),
by = .(.id, day_departure)]
# merge
dataPlot = merge(dataplot_1,
dataplot_2,
by = c(".id", "day_departure"),
all = TRUE)
# plot
ggplot(data = dataPlot[driftrate < 0, ],
aes(x = badl, y = driftrate, col = .id)) +
geom_point(show.legend = FALSE) +
geom_smooth(method = "lm", show.legend = FALSE) +
facet_wrap(.id~., scales = "free") +
labs(x = "Behavioral Aerobic Dive Limit (s)",
y = "Drift rate (m/s)") +
theme_jjo()

LS0tCnRpdGxlOiAiRGF0YSBFeHBsb3JhdGlvbiBTRVMgLSAyMDE0IgphdXRob3I6ICJKb2ZmcmV5IEpPVU1BQSIKZGF0ZTogImByIGludmlzaWJsZShTeXMuc2V0bG9jYWxlKGxvY2FsZSA9ICdDJykpOyBmb3JtYXQoU3lzLkRhdGUoKSwgZm9ybWF0ID0gJyVCICVkLCAlWScpYCIKb3V0cHV0OgogIGJvb2tkb3duOjpodG1sX2RvY3VtZW50MjoKICAgIGNzczogY29zbW9fY3VzdG9tLmNzcwogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMKICAgIGNvZGVfZm9sZGluZzogc2hvdwogICAgZGZfcHJpbnQ6IGRlZmF1bHQKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAgIGNvZGVfZG93bmxvYWQ6IHllcwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB5ZXMKICAgICAgc21vb3RoX3Njcm9sbDogbm8KbGluay1jaXRhdGlvbnM6IHllcwpwa2dkb3duOgogIGFzX2lzOiBmYWxzZQp2aWduZXR0ZTogPgogICVcVmlnbmV0dGVJbmRleEVudHJ5e0RhdGEgRXhwbG9yYXRpb24gU0VTIC0gMjAxNH0KICAlXFZpZ25ldHRlRW5naW5le2tuaXRyOjpybWFya2Rvd259CiAgJVxWaWduZXR0ZUVuY29kaW5ne1VURi04fQotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQojIGNvbW1hbmQgdG8gYnVpbGQgcGFja2FnZSB3aXRob3V0IGdldHRpbmcgdmlnbmV0dGUgZXJyb3IKIyBodHRwczovL2dpdGh1Yi5jb20vcnN0dWRpby9yZW52L2lzc3Vlcy84MzMKIyBkZXZ0b29sczo6Y2hlY2soYnVpbGRfYXJncz1jKCItLW5vLWJ1aWxkLXZpZ25ldHRlcyIpKQoKIyByZWR1Y2UgcG5nIHNpemUKa25pdHI6OmtuaXRfaG9va3Mkc2V0KG9wdGlwbmcgPSBrbml0cjo6aG9va19vcHRpcG5nKQprbml0cjo6a25pdF9ob29rcyRzZXQocG5ncXVhbnQgPSBrbml0cjo6aG9va19wbmdxdWFudCkKCiMgZ2xvYmFsIG9wdGlvbiByZWxhdGl2ZSB0byBybWFya2Rvd24Ka25pdHI6Om9wdHNfY2h1bmskc2V0KAogIGNhY2hlID0gRkFMU0UsCiAgZWNobyA9IFRSVUUsCiAgZmlnLmFsaWduID0gImNlbnRlciIsCiAgb3V0LndpZHRoID0gIjEwMCUiLAogIG1lc3NhZ2UgPSBGQUxTRSwKICB3YXJuaW5nID0gRkFMU0UsCiAgIyB0aWR5ID0gVFJVRSwKICBjYWNoZS5sYXp5ID0gRkFMU0UsCiAgb3B0aXBuZyA9ICItbzcgLXF1aWV0IiwKICBwbmdxdWFudCA9ICItLXNwZWVkPTEiCikKCiMgbGlicmFyeQpsaWJyYXJ5KGRhdGEudGFibGUpCmxpYnJhcnkobWFncml0dHIpCmxpYnJhcnkoa2FibGVFeHRyYSkKCiMgcmVtb3ZlIHNvbWUgd2FybmluZ3MKc3VwcHJlc3NXYXJuaW5ncyhsaWJyYXJ5KGdncGxvdDIpKQoKIyBkZWZpbmUgbXkgb3duIHRhYmxlIGZvcm1hdDogaHR0cHM6Ly9naXRodWIuY29tL2hhb3podTIzMy9rYWJsZUV4dHJhL2lzc3Vlcy8zNzQKc2FibGUgPC0gZnVuY3Rpb24oeCwgZXNjYXBlID0gVCwgLi4uKSB7CiAga25pdHI6OmthYmxlKHgsIGVzY2FwZSA9IGVzY2FwZSwgLi4uKSAlPiUKICAgIGthYmxlX3N0eWxpbmcoCiAgICAgIGJvb3RzdHJhcF9vcHRpb25zID0gYygic3RyaXBlZCIsICJob3ZlciIsICJyZXNwb25zaXZlIiksCiAgICAgIGZ1bGxfd2lkdGggPSBGCiAgICApCn0KYGBgCgpUaGlzIGRvY3VtZW50IGFpbXMgYXQgZXhwbG9yaW5nIHRoZSBkYXRhc2V0IG9mIDkgc291dGhlcm4taW5kaXZpZHVhbHMgaW4gMjAxNC4gRm9yIHRoYXQgcHVycG9zZSwgd2UgbmVlZCBmaXJzdCB0byBsb2FkIHRoZSBgd2VhbmxpbmdORVNgIHBhY2thZ2UgdG8gbG9hZCBkYXRhLgoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTF9CiMgbG9hZCBsaWJyYXJ5CmxpYnJhcnkod2VhbmxpbmdORVMpCgojIGxvYWQgZGF0YQpkYXRhKCJkYXRhX3NlcyIsIHBhY2thZ2UgPSAid2VhbmxpbmdORVMiKQojIGxvYWQoIi4uL2RhdGEvZGF0YV9zZXMucmRhIikKYGBgCgpMZXTigJlzIGhhdmUgYSBsb29rIGF0IHdoYXTigJlzIGluc2lkZSBgZGF0YV9zZXMkZGF0YV8yMDE0YDoKICAKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTJ9CiMgbGlzdCBzdHJ1Y3R1cmUKc3RyKGRhdGFfc2VzJHllYXJfMjAxNCwgbWF4LmxldmVsID0gMSwgZ2l2ZS5hdHRyID0gRiwgbm8ubGlzdCA9IFQpCmBgYAoKPiBBIGxpc3Qgb2YgYHIgbGVuZ3RoKGRhdGFfc2VzJHllYXJfMjAxNClgIGBkYXRhLmZyYW1lc2AsIG9uZSBmb3IgZWFjaCBzZWFsCgpGb3IgY29udmVuaWVuY2UsIHdlIGFnZ3JlZ2F0ZSBhbGwgYHIgbGVuZ3RoKGRhdGFfc2VzJHllYXJfMjAxNClgIGluZGl2aWR1YWxzIGludG8gb25lIGRhdGFzZXQuCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMywgZXZhbD1GQUxTRX0KIyBjb21iaW5lIGFsbCBpbmRpdmlkdWFscwpkYXRhXzIwMTQgPC0gcmJpbmRsaXN0KGRhdGFfc2VzJHllYXJfMjAxNCkKCiMgZGlzcGxheQpEVDo6ZGF0YXRhYmxlKGRhdGFfMjAxNFtzYW1wbGUuaW50KC5OLCAxMCksIF0sIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFggPSBUKSkKYGBgCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC00LCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30KIyBjb21iaW5lIGFsbCBpbmRpdmlkdWFscwpkYXRhXzIwMTQgPC0gcmJpbmRsaXN0KGRhdGFfc2VzJHllYXJfMjAxNCkKCiMgdGl0bGUKY2F0KCI8dGFibGUgc3R5bGU9J3dpZHRoOiA1MCUnPiIsCiAgcGFzdGUwKAogICAgIjxjYXB0aW9uPiIsCiAgICAiKCN0YWI6bXlEVGh0bWx0b29scykiLAogICAgIlNhbXBsZSBvZiAxMCByYW5kb20gcm93cyBmcm9tIGBkYXRhXzIwMTRgIiwKICAgICI8L2NhcHRpb24+IgogICksCiAgIjwvdGFibGU+IiwKICBzZXAgPSAiXG4iCikKCiMgZGlzcGxheQpEVDo6ZGF0YXRhYmxlKGRhdGFfMjAxNFtzYW1wbGUuaW50KC5OLCAxMCksIF0sIG9wdGlvbnMgPSBsaXN0KHNjcm9sbFggPSBUKSkKYGBgCgojIyBTdW1tYXJ5CgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtNX0KIyByYXdfZGF0YQpkYXRhXzIwMTRbLCAuKAogIG5iX2RheXNfcmVjb3JkZWQgPSB1bmlxdWVOKGFzLkRhdGUoZGF0ZSkpLAogIG5iX2RpdmVzID0gLk4sCiAgbWF4ZGVwdGhfbWVhbiA9IG1lYW4obWF4ZGVwdGgpLAogIGRkdXJhdGlvbl9tZWFuID0gbWVhbihkZHVyYXRpb24pLAogIGJvdHR0aW1lX21lYW4gPSBtZWFuKGJvdHR0aW1lKSwKICBwZGlfbWVhbiA9IG1lYW4ocGRpLCBuYS5ybSA9IFQpCiksIGJ5ID0gLmlkXSAlPiUKICBzYWJsZSgKICAgIGNhcHRpb24gPSAiU3VtbWFyeSBkaXZpbmcgaW5mb3JtYXRpb24gcmVsYXRpdmUgdG8gZWFjaCAyMDE4IGluZGl2aWR1YWwiLAogICAgZGlnaXRzID0gMgogICkKYGBgCgojIyBTb21lIGV4cGxhbmF0b3J5IHBsb3RzCgojIyMgTWlzc2luZyB2YWx1ZXMKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC02LCBmaWcuY2FwPSJDaGVjayBmb3IgbWlzc2luZyB2YWx1ZSBpbiAyMDE4LWluZGl2aWR1YWxzIiwgZmlnLndpZHRoPTl9CiMgYnVpbGQgZGF0YXNldCB0byBjaGVjayBmb3IgbWlzc2luZyB2YWx1ZXMKZGF0YVBsb3QgPC0gbWVsdChkYXRhXzIwMTRbLCAuKC5pZCwgaXMubmEoLlNEKSksIC5TRGNvbCA9IC1jKAogICIuaWQiLAogICJkaXZlbnVtYmVyIiwKICAieWVhciIsCiAgIm1vbnRoIiwKICAiZGF5IiwKICAiaG91ciIsCiAgIm1pbiIsCiAgInNlYyIsCiAgImp1bGRhdGUiLAogICJkaXZldHlwZSIsCiAgImRhdGUiCiAgIyAicGhhc2UiLAogICMgImxhdCIsCiAgIyAibG9uIgopXSkKIyBhZGQgdGhlIGlkIG9mIHJvd3MKZGF0YVBsb3RbLCBpZF9yb3cgOj0gYygxOi5OKSwgYnkgPSBjKCJ2YXJpYWJsZSIsICIuaWQiKV0KCiMgcGxvdApnZ3Bsb3QoZGF0YVBsb3QsIGFlcyh4ID0gdmFyaWFibGUsIHkgPSBpZF9yb3csIGZpbGwgPSB2YWx1ZSkpICsKICBnZW9tX3RpbGUoKSArCiAgbGFicyh4ID0gIkF0dHJpYnV0ZXMiLCB5ID0gIlJvd3MiKSArCiAgc2NhbGVfZmlsbF9tYW51YWwoCiAgICB2YWx1ZXMgPSBjKCJ3aGl0ZSIsICJibGFjayIpLAogICAgbGFiZWxzID0gYygiUmVhbCIsICJNaXNzaW5nIikKICApICsKICBmYWNldF93cmFwKC5pZCB+IC4sIHNjYWxlcyA9ICJmcmVlX3kiKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKAogICAgbGVnZW5kLnBvc2l0aW9uID0gInRvcCIsCiAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgbGVnZW5kLmtleSA9IGVsZW1lbnRfcmVjdChjb2xvdXIgPSAiYmxhY2siKQogICkKYGBgCgpMZXQncyBsb29rIGNsb3NlciB0byB0aGUgdmFyaWFibGVzIHdpdGggbWlzc2luZyB2YWx1ZXM6CgpgYGB7cn0KIyB0YWJsZSB3aXRoIHBlcmNlbnQKdGFibGVfaW50ZXIgPC0gZGF0YV8yMDE0WywgbGFwcGx5KC5TRCwgZnVuY3Rpb24oeCkgewogIHJvdW5kKGxlbmd0aCh4W2lzLm5hKHgpXSkgKiAxMDAgLyBsZW5ndGgoeCksIDEpCn0pLCAuU0Rjb2wgPSAtYygKICAiLmlkIiwKICAiZGl2ZW51bWJlciIsCiAgInllYXIiLAogICJtb250aCIsCiAgImRheSIsCiAgImhvdXIiLAogICJtaW4iLAogICJzZWMiLAogICJqdWxkYXRlIiwKICAiZGl2ZXR5cGUiLAogICJkYXRlIgogICMgInBoYXNlIiwKICAjICJsYXQiLAogICMgImxvbiIKKV0KCiMgZmluZCB3aGljaCBhcmUgZGlmZmVyZW50IGZyb20gMApjb25kX2ludGVyIDwtIHNhcHBseSh0YWJsZV9pbnRlciwgZnVuY3Rpb24oeCkgewogIHggPT0gMAp9KQoKIyBkaXNwbGF5IHRoZSBwZXJjZW50YWdlcyB0aGF0IGFyZSBvdmVyIDAKdGFibGVfaW50ZXJbLCB3aGljaChjb25kX2ludGVyKSA6PSBOVUxMXSAlPiUKICBzYWJsZShjYXB0aW9uID0gIlBlcmNlbnRhZ2Ugb2YgbWlzc2luZyB2YWx1ZXMgcGVyIGNvbHVtbnMgaGF2aW5nIG1pc3NpbmcgdmFsdWVzISIpICU+JQogIHNjcm9sbF9ib3god2lkdGggPSAiMTAwJSIpCmBgYAoKTm90aGluZyBiYWQsIG1pc3NpbmcgdmFsdWVzIHNlZW0gdG8gb2NjdXIgb25seSBpbiBjb2x1bW4gd2UgYXJlIG5vdCBpbnRlcmVzdGVkIGluLgoKIyMjIE91dGxpZXJzCgpMZXTigJlzIHNlZSBpZiB3ZSBoYXZlIHNvbWUgb3V0bGllcnMuIFNvbWUgb2YgdGhlbSBhcmUgcXVpZXQgZWFzeSB0byBzcG90IGxvb2tpbmcgYXQgdGhlIGRpc3RyaWJ1dGlvbiBvZiBkaXZlIGR1cmF0aW9uOgoKYGBge3IgZmlnLmNhcD0iRGlzdHJpYnV0aW9uIG9mIGBkZHVyYXRpb25gLCBgbWF4ZGVwdGhgIGFuZCBgZHJpZnRyYXRlYCBmb3IgZWFjaCBzZWFsIiwgZmlnLnNob3cgPSAiaG9sZCIsIGZpZy5oZWlnaHQ9MS41fQojIHBsb3QgdGhhdCwgd2VpcmRseSwgZG9lc24ndCBmcmVlIHggYXhpcy4uLgojIGdncGxvdCgKIyAgIG1lbHQoZGF0YV8yMDE0LAojICAgICAgICBpZC52YXJzID0gYygiLmlkIiksCiMgICAgICAgIG1lYXN1cmUudmFycyA9IGMoImRkdXJhdGlvbiIsIm1heGRlcHRoIiwiZHJpZnRyYXRlIikpLAojICAgYWVzKHggPSB2YWx1ZSwgZmlsbCA9IC5pZCkKIyApICsKIyAgIGdlb21faGlzdG9ncmFtKHNob3cubGVnZW5kID0gRkFMU0UpICsKIyAgIGZhY2V0X2dyaWQodmFyaWFibGUgfiAuaWQsCiMgICAgICAgICAgICAgIHNjYWxlcyA9ICJmcmVlIgojICAgKSArCiMgICBsYWJzKHkgPSAiIyBvZiBkaXZlcyIpICsKIyAgIHRoZW1lX2pqbygpCmdncGxvdCgKICBtZWx0KGRhdGFfMjAxNCwKICAgIGlkLnZhcnMgPSBjKCIuaWQiKSwKICAgIG1lYXN1cmUudmFycyA9IGMoImRkdXJhdGlvbiIpCiAgKSwKICBhZXMoeCA9IHZhbHVlLCBmaWxsID0gLmlkKQopICsKICBnZW9tX2hpc3RvZ3JhbShzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZmFjZXRfZ3JpZCh2YXJpYWJsZSB+IC5pZCwKICAgIHNjYWxlcyA9ICJmcmVlIgogICkgKwogIGxhYnMoeSA9ICIjIG9mIGRpdmVzIikgKwogIHRoZW1lX2pqbygpICsKICB0aGVtZSgKICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfYmxhbmsoKSwKICAgIHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpCiAgKQpnZ3Bsb3QoCiAgbWVsdChkYXRhXzIwMTQsCiAgICBpZC52YXJzID0gYygiLmlkIiksCiAgICBtZWFzdXJlLnZhcnMgPSBjKCJtYXhkZXB0aCIpCiAgKSwKICBhZXMoeCA9IHZhbHVlLCBmaWxsID0gLmlkKQopICsKICBnZW9tX2hpc3RvZ3JhbShzaG93LmxlZ2VuZCA9IEZBTFNFKSArCiAgZmFjZXRfZ3JpZCh2YXJpYWJsZSB+IC5pZCwKICAgIHNjYWxlcyA9ICJmcmVlIgogICkgKwogIHNjYWxlX3lfcmV2ZXJzZSgpICsKICBsYWJzKHkgPSAiIyBvZiBkaXZlcyIpICsKICB0aGVtZV9qam8oKSArCiAgdGhlbWUoCiAgICBzdHJpcC50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksCiAgICBheGlzLnRpdGxlLnggPSBlbGVtZW50X2JsYW5rKCksCiAgICB0ZXh0ID0gZWxlbWVudF90ZXh0KHNpemUgPSA4KQogICkKZ2dwbG90KAogIG1lbHQoZGF0YV8yMDE0LAogICAgaWQudmFycyA9IGMoIi5pZCIpLAogICAgbWVhc3VyZS52YXJzID0gYygiZHJpZnRyYXRlIikKICApLAogIGFlcyh4ID0gdmFsdWUsIGZpbGwgPSAuaWQpCikgKwogIGdlb21faGlzdG9ncmFtKHNob3cubGVnZW5kID0gRkFMU0UpICsKICBmYWNldF9ncmlkKHZhcmlhYmxlIH4gLmlkLAogICAgc2NhbGVzID0gImZyZWUiCiAgKSArCiAgbGFicyh5ID0gIiMgb2YgZGl2ZXMiKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKAogICAgc3RyaXAudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLAogICAgdGV4dCA9IGVsZW1lbnRfdGV4dChzaXplID0gOCkKICApCmBgYAoKTm90aGluZyB0aGF0IG9idmlvdXMsIHdoaWNoIGlzIGdyZWF0IDopCgojIyMgQWxsIFZhcmlhYmxlcwoKYGBge3J9Cm5hbWVzX2Rpc3BsYXkgPC0gbmFtZXMoZGF0YV8yMDE0WywgLWMoCiAgIi5pZCIsCiAgImRhdGUiLAogICJkaXZlbnVtYmVyIiwKICAieWVhciIsCiAgIm1vbnRoIiwKICAiZGF5IiwKICAiaG91ciIsCiAgIm1pbiIsCiAgInNlYyIsCiAgImp1bGRhdGUiLAogICJkaXZldHlwZSIsCiAgImRheV9kZXBhcnR1cmUiLAogICJwaGFzZSIsCiAgImxhdCIsCiAgImxvbiIsCiAgInNwIgopXSkKCiMgY2FsdWxhdGUgdGhlIG1lZGlhbiBvZiBkcmlmdHJhdGUgZm9yIGVhY2ggZGF5Cm1lZGlhbl9kcmlmdHJhdGUgPC0gZGF0YV8yMDE0W2RpdmV0eXBlID09ICIyOiBkcmlmdCIsCiAgLihkcmlmdHJhdGUgPSBxdWFudGlsZShkcmlmdHJhdGUsIDAuNSkpLAogIGJ5ID0gLihkYXRlID0gYXMuRGF0ZShkYXRlKSwgLmlkKQpdCgojIGxldCdzIGlkZW50aXR5IHdoZW4gdGhlIHNtb290aCBjaGFuZ2VzIHNpZ24KY2hhbmdlc19kcmlmdHJhdGUgPC0gbWVkaWFuX2RyaWZ0cmF0ZSAlPiUKICAuWywgLigKICAgIHlfc21vb3RoID0gcHJlZGljdChsb2VzcyhkcmlmdHJhdGUgfiBhcy5udW1lcmljKGRhdGUpLCBzcGFuID0gMC4yNSkpLAogICAgZGF0ZQogICksIGJ5ID0gLmlkXSAlPiUKICAuW2MoRkFMU0UsIGRpZmYoc2lnbih5X3Ntb290aCkpICE9IDApLCBdCmBgYAoKIyMjIyBGdWxsIHRyaXAgZHVyYXRpb24KCmBgYHtyIGV2YWw9RkFMU0UsIGluY2x1ZGU9VFJVRX0KZm9yIChpIGluIG5hbWVzX2Rpc3BsYXkpIHsKICBjYXQoIiMjIyMjIiwgaSwgInsudW5saXN0ZWQgLnVubnVtYmVyZWR9IFxuIikKICBpZiAoaSA9PSAiZHJpZnRyYXRlIikgewogICAgcHJpbnQoCiAgICAgIGdncGxvdCgKICAgICAgICBkYXRhID0gbWVsdChkYXRhXzIwMTRbLCAuKC5pZCwgZGF0ZSwgZ2V0KGkpLCBkaXZldHlwZSldLAogICAgICAgICAgaWQudmFycyA9IGMoIi5pZCIsICJkYXRlIiwgImRpdmV0eXBlIikKICAgICAgICApLAogICAgICAgIGFlcygKICAgICAgICAgIHggPSBhcy5EYXRlKGRhdGUpLAogICAgICAgICAgeSA9IHZhbHVlLAogICAgICAgICAgY29sID0gZGl2ZXR5cGUKICAgICAgICApCiAgICAgICkgKwogICAgICAgIGdlb21fcG9pbnQoCiAgICAgICAgICBhbHBoYSA9IDEgLyAxMCwKICAgICAgICAgIHNpemUgPSAuNQogICAgICAgICkgKwogICAgICAgIGdlb21fdmxpbmUoCiAgICAgICAgICBkYXRhID0gY2hhbmdlc19kcmlmdHJhdGUsCiAgICAgICAgICBhZXMoeGludGVyY2VwdCA9IGRhdGUpLAogICAgICAgICAgbGluZXR5cGUgPSAyCiAgICAgICAgKSArCiAgICAgICAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHMgPSAiJW0vJVkiKSArCiAgICAgICAgbGFicyh4ID0gIkRhdGUiLCB5ID0gIkRyaWZ0IFJhdGUgbS9zIiwgY29sID0gIkRpdmUgVHlwZSIpICsKICAgICAgICB0aGVtZV9qam8oKSArCiAgICAgICAgdGhlbWUoCiAgICAgICAgICBheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpLAogICAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIKICAgICAgICApICsKICAgICAgICBndWlkZXMoY29sb3VyID0gZ3VpZGVfbGVnZW5kKG92ZXJyaWRlLmFlcyA9IGxpc3QoCiAgICAgICAgICBzaXplID0gNywKICAgICAgICAgIGFscGhhID0gMQogICAgICAgICkpKQogICAgKQogIH0gZWxzZSB7CiAgICBwcmludCgKICAgICAgZ2dwbG90KAogICAgICAgIGRhdGEgPSBtZWx0KGRhdGFfMjAxNFssIC4oLmlkLCBkYXRlLCBnZXQoaSkpXSwKICAgICAgICAgIGlkLnZhcnMgPSBjKCIuaWQiLCAiZGF0ZSIpCiAgICAgICAgKSwKICAgICAgICBhZXMoCiAgICAgICAgICB4ID0gYXMuRGF0ZShkYXRlKSwKICAgICAgICAgIHkgPSB2YWx1ZSwKICAgICAgICAgIGNvbCA9IC5pZAogICAgICAgICkKICAgICAgKSArCiAgICAgICAgZ2VvbV9wb2ludCgKICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UsCiAgICAgICAgICBhbHBoYSA9IDEgLyAxMCwKICAgICAgICAgIHNpemUgPSAuNQogICAgICAgICkgKwogICAgICAgIGdlb21fdmxpbmUoCiAgICAgICAgICBkYXRhID0gY2hhbmdlc19kcmlmdHJhdGUsCiAgICAgICAgICBhZXMoeGludGVyY2VwdCA9IGRhdGUpLAogICAgICAgICAgbGluZXR5cGUgPSAyCiAgICAgICAgKSArCiAgICAgICAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgICBzY2FsZV94X2RhdGUoZGF0ZV9sYWJlbHMgPSAiJW0vJVkiKSArCiAgICAgICAgbGFicyh4ID0gIkRhdGUiLCB5ID0gaSkgKwogICAgICAgIHRoZW1lX2pqbygpICsKICAgICAgICB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDQ1LCBoanVzdCA9IDEpKQogICAgKQogIH0KCiAgY2F0KCJcbiBcbiIpCn0KYGBgCgpUaGUgdmVydGljYWwgZGFzaGVkIGxpbmVzIHJlcHJlc2VudCBjaGFuZ2VzIGluIGJ1b3lhbmN5IChzZWUgYHZpZ25ldHRlKCJidW95YW5jeV9kZXRlY3QiKWAgZm9yIG1vcmUgaW5mb3JtYXRpb24pCgojIyMjIHsudW5saXN0ZWQgLnVubnVtYmVyZWQgLnRhYnNldCAudGFic2V0LWZhZGUgLnRhYnNldC1waWxsc30KCmBgYHtyIHJlc3VsdHM9J2FzaXMnLCBjYWNoZT1UUlVFLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTd9CmZvciAoaSBpbiBuYW1lc19kaXNwbGF5KSB7CiAgY2F0KCIjIyMjIyIsIGksICJ7LnVubGlzdGVkIC51bm51bWJlcmVkfSBcbiIpCiAgaWYgKGkgPT0gImRyaWZ0cmF0ZSIpIHsKICAgIHByaW50KAogICAgICBnZ3Bsb3QoCiAgICAgICAgZGF0YSA9IG1lbHQoZGF0YV8yMDE0WywgLiguaWQsIGRhdGUsIGdldChpKSwgZGl2ZXR5cGUpXSwKICAgICAgICAgIGlkLnZhcnMgPSBjKCIuaWQiLCAiZGF0ZSIsICJkaXZldHlwZSIpCiAgICAgICAgKSwKICAgICAgICBhZXMoCiAgICAgICAgICB4ID0gYXMuRGF0ZShkYXRlKSwKICAgICAgICAgIHkgPSB2YWx1ZSwKICAgICAgICAgIGNvbCA9IGRpdmV0eXBlCiAgICAgICAgKQogICAgICApICsKICAgICAgICBnZW9tX3BvaW50KAogICAgICAgICAgYWxwaGEgPSAxIC8gMTAsCiAgICAgICAgICBzaXplID0gLjUKICAgICAgICApICsKICAgICAgICBnZW9tX3ZsaW5lKAogICAgICAgICAgZGF0YSA9IGNoYW5nZXNfZHJpZnRyYXRlLAogICAgICAgICAgYWVzKHhpbnRlcmNlcHQgPSBkYXRlKSwKICAgICAgICAgIGxpbmV0eXBlID0gMgogICAgICAgICkgKwogICAgICAgIGZhY2V0X3dyYXAoLiB+IC5pZCwgc2NhbGVzID0gImZyZWUiKSArCiAgICAgICAgc2NhbGVfeF9kYXRlKGRhdGVfbGFiZWxzID0gIiVtLyVZIikgKwogICAgICAgIGxhYnMoeCA9ICJEYXRlIiwgeSA9ICJEcmlmdCBSYXRlIG0vcyIsIGNvbCA9ICJEaXZlIFR5cGUiKSArCiAgICAgICAgdGhlbWVfampvKCkgKwogICAgICAgIHRoZW1lKAogICAgICAgICAgYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSwKICAgICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9ICJib3R0b20iCiAgICAgICAgKSArCiAgICAgICAgZ3VpZGVzKGNvbG91ciA9IGd1aWRlX2xlZ2VuZChvdmVycmlkZS5hZXMgPSBsaXN0KAogICAgICAgICAgc2l6ZSA9IDcsCiAgICAgICAgICBhbHBoYSA9IDEKICAgICAgICApKSkKICAgICkKICB9IGVsc2UgewogICAgcHJpbnQoCiAgICAgIGdncGxvdCgKICAgICAgICBkYXRhID0gbWVsdChkYXRhXzIwMTRbLCAuKC5pZCwgZGF0ZSwgZ2V0KGkpKV0sCiAgICAgICAgICBpZC52YXJzID0gYygiLmlkIiwgImRhdGUiKQogICAgICAgICksCiAgICAgICAgYWVzKAogICAgICAgICAgeCA9IGFzLkRhdGUoZGF0ZSksCiAgICAgICAgICB5ID0gdmFsdWUsCiAgICAgICAgICBjb2wgPSAuaWQKICAgICAgICApCiAgICAgICkgKwogICAgICAgIGdlb21fcG9pbnQoCiAgICAgICAgICBzaG93LmxlZ2VuZCA9IEZBTFNFLAogICAgICAgICAgYWxwaGEgPSAxIC8gMTAsCiAgICAgICAgICBzaXplID0gLjUKICAgICAgICApICsKICAgICAgICBnZW9tX3ZsaW5lKAogICAgICAgICAgZGF0YSA9IGNoYW5nZXNfZHJpZnRyYXRlLAogICAgICAgICAgYWVzKHhpbnRlcmNlcHQgPSBkYXRlKSwKICAgICAgICAgIGxpbmV0eXBlID0gMgogICAgICAgICkgKwogICAgICAgIGZhY2V0X3dyYXAoLiB+IC5pZCwgc2NhbGVzID0gImZyZWUiKSArCiAgICAgICAgc2NhbGVfeF9kYXRlKGRhdGVfbGFiZWxzID0gIiVtLyVZIikgKwogICAgICAgIGxhYnMoeCA9ICJEYXRlIiwgeSA9IGkpICsKICAgICAgICB0aGVtZV9qam8oKSArCiAgICAgICAgdGhlbWUoYXhpcy50ZXh0LnggPSBlbGVtZW50X3RleHQoYW5nbGUgPSA0NSwgaGp1c3QgPSAxKSkKICAgICkKICB9CgogIGNhdCgiXG4gXG4iKQp9CmBgYAoKIyMjIyBGaXJzdCBtb250aCBhdCBzZWEKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0xOCwgZXZhbD1GQUxTRSwgaW5jbHVkZT1UUlVFfQpmb3IgKGkgaW4gbmFtZXNfZGlzcGxheSkgewogICMgc3VidGl0bGUKICBjYXQoIiMjIyMjIiwgaSwgInsudW5saXN0ZWQgLnVubnVtYmVyZWR9IFxuIikKICAKICAjIHByaW50IHBsb3QKICBwcmludCgKICAgICAgZ2dwbG90KAogICAgICAgIGRhdGEgPSBtZWx0KGRhdGFfMjAxNFtkYXlfZGVwYXJ0dXJlIDwgMzIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLiguaWQsIGRheV9kZXBhcnR1cmUsIGdldChpKSldLCAKICAgICAgICAgICAgICAgICAgICBpZC52YXJzID0gYygiLmlkIiwgImRheV9kZXBhcnR1cmUiKSksCiAgICAgICAgYWVzKAogICAgICAgICAgeCA9IGRheV9kZXBhcnR1cmUsCiAgICAgICAgICB5ID0gdmFsdWUsCiAgICAgICAgICBjb2xvciA9IC5pZCwKICAgICAgICAgIGdyb3VwID0gZGF5X2RlcGFydHVyZQogICAgICAgICkKICAgICAgKSArCiAgICAgICAgZ2VvbV9ib3hwbG90KAogICAgICAgICAgc2hvdy5sZWdlbmQgPSBGQUxTRSwKICAgICAgICAgIGFscGhhID0gMSAvIDEwLAogICAgICAgICAgc2l6ZSA9IC41CiAgICAgICAgKSArCiAgICAgICAgZmFjZXRfd3JhcCguIH4gLmlkLCBzY2FsZXMgPSAiZnJlZSIpICsKICAgICAgICBsYWJzKHggPSAiIyBkYXlzIHNpbmNlIGRlcGFydHVyZSIsIHkgPSBpKSArCiAgICAgICAgdGhlbWVfampvKCkKICAgICkKICBjYXQoIlxuIFxuIikKfQpgYGAKCiMjIyMgey51bmxpc3RlZCAudW5udW1iZXJlZCAudGFic2V0IC50YWJzZXQtZmFkZSAudGFic2V0LXBpbGxzfQoKYGBge3IgZGF0YS1leHBsb3JhdGlvbi0yMDE4LTE5LCByZXN1bHRzPSdhc2lzJywgY2FjaGU9VFJVRSwgZWNobz1GQUxTRX0KZm9yIChpIGluIG5hbWVzX2Rpc3BsYXkpIHsKICAjIHN1YnRpdGxlCiAgY2F0KCIjIyMjIyIsIGksICJ7LnVubGlzdGVkIC51bm51bWJlcmVkfSBcbiIpCiAgCiAgIyBwcmludCBwbG90CiAgcHJpbnQoCiAgICAgIGdncGxvdCgKICAgICAgICBkYXRhID0gbWVsdChkYXRhXzIwMTRbZGF5X2RlcGFydHVyZSA8IDMyLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4oLmlkLCBkYXlfZGVwYXJ0dXJlLCBnZXQoaSkpXSwgCiAgICAgICAgICAgICAgICAgICAgaWQudmFycyA9IGMoIi5pZCIsICJkYXlfZGVwYXJ0dXJlIikpLAogICAgICAgIGFlcygKICAgICAgICAgIHggPSBkYXlfZGVwYXJ0dXJlLAogICAgICAgICAgeSA9IHZhbHVlLAogICAgICAgICAgY29sb3IgPSAuaWQsCiAgICAgICAgICBncm91cCA9IGRheV9kZXBhcnR1cmUKICAgICAgICApCiAgICAgICkgKwogICAgICAgIGdlb21fYm94cGxvdCgKICAgICAgICAgIHNob3cubGVnZW5kID0gRkFMU0UsCiAgICAgICAgICBhbHBoYSA9IDEgLyAxMCwKICAgICAgICAgIHNpemUgPSAuNQogICAgICAgICkgKwogICAgICAgIGZhY2V0X3dyYXAoLiB+IC5pZCwgc2NhbGVzID0gImZyZWUiKSArCiAgICAgICAgbGFicyh4ID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiLCB5ID0gaSkgKwogICAgICAgIHRoZW1lX2pqbygpCiAgICApCiAgY2F0KCJcbiBcbiIpCn0KYGBgCgojIyBEaXZlIFR5cGUKCmBgYHtyIGZpZy5jYXAgPSAiRXZvbHV0aW9uIG9mIGRpdmUgdHlwZSBwcm9wb3J0aW9uIn0KIyBkYXRhc2V0IHRvIHBsb3QgcHJvcG9ydGlvbmFsIGFyZWEgcGxvdApkYXRhXzIwMTRbLCBzdW1faWQgOj0gLk4sIGJ5ID0gLiguaWQsIGRheV9kZXBhcnR1cmUpXSAlPiUKICAuWywgc3VtX2lkX2RheXMgOj0gLk4sIGJ5ID0gLiguaWQsIGRheV9kZXBhcnR1cmUsIGRpdmV0eXBlKV0gJT4lCiAgLlssIHByb3AgOj0gc3VtX2lkX2RheXMgLyBzdW1faWRdCmRhdGFQbG90IDwtIHVuaXF1ZShkYXRhXzIwMTRbLCAuKHByb3AsIC5pZCwgZGl2ZXR5cGUsIGRheV9kZXBhcnR1cmUpXSkKCiMgYXJlYSBwbG90CmdncGxvdChkYXRhUGxvdCwgYWVzKAogIHggPSBhcy5udW1lcmljKGRheV9kZXBhcnR1cmUpLAogIHkgPSBwcm9wLAogIGZpbGwgPSBhcy5jaGFyYWN0ZXIoZGl2ZXR5cGUpCikpICsKICBnZW9tX2FyZWEoYWxwaGEgPSAwLjYsIHNpemUgPSAxKSArCiAgZmFjZXRfd3JhcCguaWQgfiAuLCBzY2FsZXMgPSAiZnJlZSIpICsKICB0aGVtZV9qam8oKSArCiAgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gImJvdHRvbSIpICsKICBsYWJzKHggPSAiIyBvZiBkYXlzIHNpbmNlIGRlcGFydHVyZSIsIAogICAgICAgeSA9ICJQcm9wb3J0aW9uIG9mIGRpdmVzIiwgCiAgICAgICBmaWxsID0gIkRpdmUgdHlwZXMiKQpgYGAKCiMjIERyaWZ0IFJhdGUKCj4gSW4gdGhlIGZvbGxvd2luZyBncmFwaHM6Cj4KPiAqIGBkcmlmdHJhdGVgIGlzIGNhbGN1bGF0ZWQgdXNpbmcgb25seSBgZGl2ZXR5cGUgPT0gIjI6IGRyaWZ0ImAKPiAqIHdoZXJlYXMgYWxsIHRoZSBvdGhlcnMgdmFyaWFibGVzIGFyZSBjYWxjdWxhdGVkIGFsbCBkaXZlcyBjb25zaWRlcmVkCj4gKiBEaXZlcyB3ZXJlIGBkcmlmdHJhdGUgPiAwYCB3ZXJlIGV4Y2x1ZGVkCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMjl9CiMgYnVpbGQgZGF0YXNldApkYXRhUGxvdCA8LSBkYXRhXzIwMTRbZGl2ZXR5cGUgPT0gIjI6IGRyaWZ0IiAmCiAgICAgICAgICAgICAgICAgICAgICAgIGRyaWZ0cmF0ZSA8IDAsCiAgICAgICAgICAgICAgICAgICAgICAjIG1lZGlhbiBkcmlmdCByYXRlIGZvciBkcmlmdCBkaXZlCiAgICAgICAgICAgICAgICAgICAgICAuKGRyaWZ0cmF0ZSA9IG1lZGlhbihkcmlmdHJhdGUsIG5hLnJtID0gVCkpLAogICAgICAgICAgICAgICAgICAgICAgYnkgPSAuKC5pZCwgZGF5X2RlcGFydHVyZSldICU+JQogICMgbWVyZ2UgdG8gZ2V0IG90aGVyIHBhcmFtZXRlcnMgaW5jbHVkaW5nIGFsbCBkaXZlcwogIC5bZGF0YV8yMDE0W2RyaWZ0cmF0ZSA8IDAsCiAgICAgICAgICAgICAgLigKICAgICAgICAgICAgICAgICMgbWVkaWFuIGRpdmUgZHVyYXRpb24gYWxsIGRpdmVzIGNvbnNpZGVyZWQKICAgICAgICAgICAgICAgIGRkdXJhdGlvbiA9IG1lZGlhbihkZHVyYXRpb24sIG5hLnJtID0gVCksCiAgICAgICAgICAgICAgICAjIG1lZGlhbiBtYXggZGVwdGggYWxsIGRpdmVzIGNvbnNpZGVyZWQKICAgICAgICAgICAgICAgIG1heGRlcHRoID0gbWVkaWFuKG1heGRlcHRoLCBuYS5ybSA9IFQpLAogICAgICAgICAgICAgICAgIyBtZWRpYW4gYm90dG9tIGRpdmVzIGFsbCBkaXZlcyBjb25zaWRlcmVkCiAgICAgICAgICAgICAgICBib3R0dGltZSA9IG1lZGlhbihib3R0dGltZSwgbmEucm0gPSBUKQogICAgICAgICAgICAgICksCiAgICAgICAgICAgICAgYnkgPSAuKC5pZCwgZGF5X2RlcGFydHVyZSldLAogICAgb24gPSBjKCIuaWQiLCAiZGF5X2RlcGFydHVyZSIpXQpgYGAKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0zMCwgZmlnLmNhcD0iRHJpZnQgcmF0ZSB2cy4gQm90dG9tIHRpbWUifQojIHBsb3QKZ2dwbG90KGRhdGFQbG90LCBhZXMoeCA9IGJvdHR0aW1lLCB5ID0gZHJpZnRyYXRlLCBjb2wgPSAuaWQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gLjUsIGFscGhhID0gLjUpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArCiAgZ3VpZGVzKGNvbG9yID0gIm5vbmUiKSArCiAgZmFjZXRfd3JhcCguaWQgfiAuKSArCiAgc2NhbGVfeF9jb250aW51b3VzKGxpbWl0cyA9IGMoMCwgNzAwKSkgKwogIGxhYnMoeCA9ICJEYWlseSBtZWRpYW4gQm90dG9tIHRpbWUgKHMpIiwgCiAgICAgICB5ID0gIkRhaWx5IG1lZGlhbiBkcmlmdCByYXRlIChtLnMtMSkiKSArCiAgdGhlbWVfampvKCkKYGBgCgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMzEsIGZpZy5jYXA9IkRyaWZ0IHJhdGUgdnMuIE1heGltdW0gZGVwdGgifQojIHBsb3QKZ2dwbG90KGRhdGFQbG90LCBhZXMoeCA9IG1heGRlcHRoLCB5ID0gZHJpZnRyYXRlLCBjb2wgPSAuaWQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gLjUsIGFscGhhID0gLjUpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArCiAgZ3VpZGVzKGNvbG9yID0gIm5vbmUiKSArCiAgc2NhbGVfeV9yZXZlcnNlKCkgKwogIGZhY2V0X3dyYXAoLmlkIH4gLikgKwogIGxhYnMoeCA9ICJEYWlseSBtZWRpYW4gTWF4aW11bSBkZXB0aCAobSkiLCAKICAgICAgIHkgPSAiRGFpbHkgbWVkaWFuIGRyaWZ0IHJhdGUgKG0ucy0xKSIpICsKICB0aGVtZV9qam8oKQpgYGAKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0zMiwgZmlnLmNhcD0iRHJpZnQgcmF0ZSB2cy4gRGl2ZSBkdXJhdGlvbiJ9CiMgcGxvdApnZ3Bsb3QoZGF0YVBsb3QsIGFlcyh4ID0gZGR1cmF0aW9uLCB5ID0gZHJpZnRyYXRlLCBjb2wgPSAuaWQpKSArCiAgZ2VvbV9wb2ludChzaXplID0gLjUsIGFscGhhID0gLjUpICsKICBnZW9tX3Ntb290aChtZXRob2QgPSAibG0iKSArCiAgZ3VpZGVzKGNvbG9yID0gIm5vbmUiKSArCiAgZmFjZXRfd3JhcCguaWQgfiAuKSArCiAgbGFicyh4ID0gIkRhaWx5IG1lZGlhbiBEaXZlIGR1cmF0aW9uIChzKSIsIAogICAgICAgeSA9ICJEYWlseSBtZWRpYW4gZHJpZnQgcmF0ZSAobS5zLTEpIikgKwogIHRoZW1lX2pqbygpCmBgYAoKIyMgQmVoYXZpb3JhbCBBZXJvYmljIERpdmUgTGltaXQgKGJBREwpCgpCYXNlZCBvbiBbU2hlcm8gZXQgKmFsLiogKDIwMTgpXShodHRwczovL3d3dy5yZXNlYXJjaGdhdGUubmV0L3B1YmxpY2F0aW9uLzIyMjY4MzA0Ml9Ub19icmVhdGhlX29yX25vdF90b19icmVhdGhlX09wdGltYWxfYnJlYXRoaW5nX2Flcm9iaWNfZGl2ZV9saW1pdF9hbmRfb3h5Z2VuX3N0b3Jlc19pbl9kZWVwLWRpdmluZ19ibHVlLWV5ZWRfc2hhZ3MpLCB3ZSBkZWNpZGVkIHRvIGxvb2sgYXQgdGhlICpiQURMKiBhcyB0aGUgOTV0aCBwZXJjZW50aWxlIG9mIGRpdmUgZHVyYXRpb24gZWFjaCBkYXksIGZvciB0aG9zZSB3aXRoICRuIFxnZXEgOCQuIFRoaXMgdGhyZXNob2xkIHdhcyBjaG9zZW4gZm9sbG93aW5nIHRoaXMgZmlndXJlLCBwbGVhc2Ugbm90ZSB0aGF0IHRoaXMgbnVtYmVyIGlzIHBhcnRpY3VsYXJseSBsb3cgY2F1c2Ugb25seSBvbmUgZGl2ZSBldmVyeSAyLjIgaG91cnMgd2FzIHNhbXBsZWQ6CgpgYGB7ciBkYXRhLWV4cGxvcmF0aW9uLTIwMTgtMzYsIGZpZy5jYXA9IkRpc3RyaWJ1dGlvbiBvZiB0aGUgbnVtYmVyIG9mIGRpdmVzIGVhY2ggZGF5LiBUaGUgdGhyZXNob2xkIHVzZWQgdG8gY2FsY3VsYXRlIGJBREwgaXMgZml4ZWQgYXQgNTAgZGl2ZXMgcGVyIGRheS4iLCBmaWcuaGVpZ2h0PTN9CmdncGxvdChkYXRhXzIwMTRbLC4obmJfZGl2ZXMgPSAuTiksIAogICAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlKV0sIAogICAgICAgYWVzKHg9bmJfZGl2ZXMsIGZpbGw9LmlkKSkgKwogIGdlb21faGlzdG9ncmFtKHNob3cubGVnZW5kID0gRkFMU0UpICsgCiAgZmFjZXRfd3JhcCgufi5pZCkgKwogIGxhYnMoeT0iIyBvZiBkYXlzIiwgeCA9ICIjIG9mIGRpdmVzIHBlciBkYXkiKSArCiAgdGhlbWVfampvKCkgKwogIHRoZW1lKHRleHQgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDgpKQpgYGAKCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0zNywgZmlnLmNhcD0iQmVoYXZpb3JhbCBBREwgdnMuIGRyaWZ0IHJhdGUgYWxvbmcgYW5pbWFscycgdHJpcCAoQW0gSSB0aGUgb25seSBvbmUgc2VlaW5nIHNvbWUga2luZCBvZiByZWxhdGlvbnNoaXA/KSJ9CiMgc2VsZWN0IGRheSB0aGF0IGhhdmUgYXQgbGVhc3QgNTAgZGl2ZXMKZGF5c190b19rZWVwID0gZGF0YV8yMDE0WywKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAuKG5iX2RpdmVzID0gLk4pLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGJ5ID0gLiguaWQsIGRheV9kZXBhcnR1cmUpXSAlPiUKICAuW25iX2RpdmVzID49IDgsXQoKIyBrZWVwIG9ubHkgdGhvc2UgZGF5cwpkYXRhXzIwMTRfY29tcGxldGVfZGF5ID0gbWVyZ2UoZGF0YV8yMDE0LAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGRheXNfdG9fa2VlcCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IGMoIi5pZCIsICJkYXlfZGVwYXJ0dXJlIikpCgojIGRhdGEgcGxvdApkYXRhUGxvdCA9IGRhdGFfMjAxNF9jb21wbGV0ZV9kYXlbZGl2ZXR5cGU9PSIxOiBmb3JhZ2luZyIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLihiYWRsID0gcXVhbnRpbGUoZGR1cmF0aW9uLCAwLjk1KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYnkgPSAuKC5pZCwgZGF5X2RlcGFydHVyZSldCgojIGNvbWJpbmUgdHdvIGRhdGFzZXRzIHRvIGJlIGFibGUgdG8gdXNlIGEgc2Vjb25kIGF4aXMKIyBodHRwczovL3N0YWNrb3ZlcmZsb3cuY29tL3F1ZXN0aW9ucy80OTE4NTU4My90d28teS1heGVzLXdpdGgtZGlmZmVyZW50LXNjYWxlcy1mb3ItdHdvLWRhdGFzZXRzLWluLWdncGxvdDIKZGF0YU1lZ2FQbG90ID0gcmJpbmQoZGF0YV8yMDE0X2NvbXBsZXRlX2RheVtkaXZldHlwZSA9PSAiMjogZHJpZnQiXSAlPiUKICAgICAgICAgICAgICAgICAgICAgICAuWywgLih3ID0gLmlkLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgIHkgPSBkcmlmdHJhdGUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeCA9IGRheV9kZXBhcnR1cmUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgeiA9ICJzZWNvbmRfcGxvdCIpXSwKICAgICAgICAgICAgICAgICAgICAgZGF0YVBsb3RbLCAuKAogICAgICAgICAgICAgICAgICAgICAgIHcgPSAuaWQsCiAgICAgICAgICAgICAgICAgICAgICAgIyB0cmlja3kgb25lCiAgICAgICAgICAgICAgICAgICAgICAgeSA9IChiYWRsIC8gMTAwMCkgLSAxLAogICAgICAgICAgICAgICAgICAgICAgIHggPSBkYXlfZGVwYXJ0dXJlLAogICAgICAgICAgICAgICAgICAgICAgIHogPSAiZmlyc3RfcGxvdCIKICAgICAgICAgICAgICAgICAgICAgKV0pCgojIHBsb3QKZ2dwbG90KCkgKwogIGdlb21fcG9pbnQoCiAgICBkYXRhID0gZGF0YU1lZ2FQbG90W3ogPT0gInNlY29uZF9wbG90IiwgXSwKICAgIGFlcyh4ID0geCwgeSA9IHkpLAogICAgYWxwaGEgPSAxIC8gMTAsCiAgICBzaXplID0gMC41LAogICAgY29sb3IgPSAiZ3JleTQwIiwKICAgIHNob3cubGVnZW5kID0gRkFMU0UKICApICsKICBnZW9tX3BhdGgoZGF0YSA9IGRhdGFNZWdhUGxvdFt6ID09ICJmaXJzdF9wbG90IiwgXSwKICAgICAgICAgICAgYWVzKHggPSB4LCB5ID0geSwgY29sb3IgPSB3KSwKICAgICAgICAgICAgc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIHNjYWxlX3lfY29udGludW91cygKICAgICMgRmVhdHVyZXMgb2YgdGhlIGZpcnN0IGF4aXMKICAgIG5hbWUgPSAiRHJpZnQgcmF0ZSAobS9zKSIsCiAgICAjIEFkZCBhIHNlY29uZCBheGlzIGFuZCBzcGVjaWZ5IGl0cyBmZWF0dXJlcwogICAgc2VjLmF4aXMgPSBzZWNfYXhpcyggfiAoLiAqIDEwMDApICsgMTAwMCwgCiAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lID0gIkJlaGF2aW9yYWwgQWVyb2JpYyBEaXZlIExpbWl0IChzKSIpCiAgKSArCiAgbGFicyh4ID0gIiMgZGF5cyBzaW5jZSBkZXBhcnR1cmUiKSArCiAgZmFjZXRfd3JhcCh3IH4gLikgKwogIHRoZW1lX2pqbygpCmBgYAoKPiBMb29raW5nIGF0IHRoaXMgZ3JhcGgsIEkgd2FudCB0byBiZWxpZXZlIHRoYXQgdGhlcmUgaXMgc29tZSBraW5kIG9mIHJlbGF0aW9uc2hpcCBiZXR3ZWVuIHRoZSAqYkFETCogYXMgZGVmaW5lZCBieSBbU2hlcm8gZXQgKmFsLiogKDIwMTgpXShodHRwczovL3d3dy5yZXNlYXJjaGdhdGUubmV0L3B1YmxpY2F0aW9uLzIyMjY4MzA0Ml9Ub19icmVhdGhlX29yX25vdF90b19icmVhdGhlX09wdGltYWxfYnJlYXRoaW5nX2Flcm9iaWNfZGl2ZV9saW1pdF9hbmRfb3h5Z2VuX3N0b3Jlc19pbl9kZWVwLWRpdmluZ19ibHVlLWV5ZWRfc2hhZ3MpIGFuZCB0aGUgZHJpZnQgcmF0ZSAoYW5kIHNvIGJ1eW9hbmN5KS4KCmBgYHtyIGRhdGEtZXhwbG9yYXRpb24tMjAxOC0zOH0KIyBnZXQgYmFkbApkYXRhcGxvdF8xID0gZGF0YV8yMDE0X2NvbXBsZXRlX2RheVssCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4oYmFkbCA9IHF1YW50aWxlKGRkdXJhdGlvbiwgMC45NSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlKV0KIyBnZXQgZHJpZnRyYXRlCmRhdGFwbG90XzIgPSBkYXRhXzIwMTRfY29tcGxldGVfZGF5W2RpdmV0eXBlID09ICIyOiBkcmlmdCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC4oZHJpZnRyYXRlID0gbWVkaWFuKGRyaWZ0cmF0ZSkpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBieSA9IC4oLmlkLCBkYXlfZGVwYXJ0dXJlKV0KCiMgbWVyZ2UKZGF0YVBsb3QgPSBtZXJnZShkYXRhcGxvdF8xLAogICAgICAgICAgICAgICAgIGRhdGFwbG90XzIsCiAgICAgICAgICAgICAgICAgYnkgPSBjKCIuaWQiLCAiZGF5X2RlcGFydHVyZSIpLAogICAgICAgICAgICAgICAgIGFsbCA9IFRSVUUpCgojIHBsb3QKZ2dwbG90KGRhdGEgPSBkYXRhUGxvdFtkcmlmdHJhdGUgPCAwLCBdLCAKICAgICAgIGFlcyh4ID0gYmFkbCwgeSA9IGRyaWZ0cmF0ZSwgY29sID0gLmlkKSkgKwogIGdlb21fcG9pbnQoc2hvdy5sZWdlbmQgPSBGQUxTRSkgKwogIGdlb21fc21vb3RoKG1ldGhvZCA9ICJsbSIsIHNob3cubGVnZW5kID0gRkFMU0UpICsKICBmYWNldF93cmFwKC5pZH4uLCBzY2FsZXMgPSAiZnJlZSIpICsKICBsYWJzKHggPSAiQmVoYXZpb3JhbCBBZXJvYmljIERpdmUgTGltaXQgKHMpIiwKICAgICAgIHkgPSAiRHJpZnQgcmF0ZSAobS9zKSIpICsKICB0aGVtZV9qam8oKQpgYGAK